﻿using System;

public class Tile
{
    internal int c;
    internal int fbIndex;
    internal int h;
    internal int incX;
    internal int incY;
    public bool initialized;
    public bool[] opaque = new bool[8];
    internal int palIndex;
    internal int[] pix = new int[0x40];
    internal int tIndex;
    internal int tpri;
    internal int w;
    internal int x;
    internal int y;

    public virtual void dumpData(string file)
    {
    }

    public virtual bool isTransparent(int x, int y)
    {
        return (this.pix[(y << 3) + x] == 0);
    }

    public virtual void render(int srcx1, int srcy1, int srcx2, int srcy2, int dx, int dy, int[] fBuffer, int palAdd, int[] palette, bool flipHorizontal, bool flipVertical, int pri, int[] priTable)
    {
        if (((dx >= -7) && (dx < 0x100)) && ((dy >= -7) && (dy < 240)))
        {
            this.w = srcx2 - srcx1;
            this.h = srcy2 - srcy1;
            if (dx < 0)
            {
                srcx1 -= dx;
            }
            if ((dx + srcx2) >= 0x100)
            {
                srcx2 = 0x100 - dx;
            }
            if (dy < 0)
            {
                srcy1 -= dy;
            }
            if ((dy + srcy2) >= 240)
            {
                srcy2 = 240 - dy;
            }
            if (!flipHorizontal && !flipVertical)
            {
                this.fbIndex = (dy << 8) + dx;
                this.tIndex = 0;
                this.y = 0;
                while (this.y < 8)
                {
                    this.x = 0;
                    while (this.x < 8)
                    {
                        if (((this.x >= srcx1) && (this.x < srcx2)) && ((this.y >= srcy1) && (this.y < srcy2)))
                        {
                            this.palIndex = this.pix[this.tIndex];
                            this.tpri = priTable[this.fbIndex];
                            if ((this.palIndex != 0) && (pri <= (this.tpri & 0xff)))
                            {
                                fBuffer[this.fbIndex] = palette[this.palIndex + palAdd];
                                this.tpri = (this.tpri & 0xf00) | pri;
                                priTable[this.fbIndex] = this.tpri;
                            }
                        }
                        this.fbIndex++;
                        this.tIndex++;
                        this.x++;
                    }
                    this.fbIndex -= 8;
                    this.fbIndex += 0x100;
                    this.y++;
                }
            }
            else if (flipHorizontal && !flipVertical)
            {
                this.fbIndex = (dy << 8) + dx;
                this.tIndex = 7;
                this.y = 0;
                while (this.y < 8)
                {
                    this.x = 0;
                    while (this.x < 8)
                    {
                        if (((this.x >= srcx1) && (this.x < srcx2)) && ((this.y >= srcy1) && (this.y < srcy2)))
                        {
                            this.palIndex = this.pix[this.tIndex];
                            this.tpri = priTable[this.fbIndex];
                            if ((this.palIndex != 0) && (pri <= (this.tpri & 0xff)))
                            {
                                fBuffer[this.fbIndex] = palette[this.palIndex + palAdd];
                                this.tpri = (this.tpri & 0xf00) | pri;
                                priTable[this.fbIndex] = this.tpri;
                            }
                        }
                        this.fbIndex++;
                        this.tIndex--;
                        this.x++;
                    }
                    this.fbIndex -= 8;
                    this.fbIndex += 0x100;
                    this.tIndex += 0x10;
                    this.y++;
                }
            }
            else if (flipVertical && !flipHorizontal)
            {
                this.fbIndex = (dy << 8) + dx;
                this.tIndex = 0x38;
                this.y = 0;
                while (this.y < 8)
                {
                    this.x = 0;
                    while (this.x < 8)
                    {
                        if (((this.x >= srcx1) && (this.x < srcx2)) && ((this.y >= srcy1) && (this.y < srcy2)))
                        {
                            this.palIndex = this.pix[this.tIndex];
                            this.tpri = priTable[this.fbIndex];
                            if ((this.palIndex != 0) && (pri <= (this.tpri & 0xff)))
                            {
                                fBuffer[this.fbIndex] = palette[this.palIndex + palAdd];
                                this.tpri = (this.tpri & 0xf00) | pri;
                                priTable[this.fbIndex] = this.tpri;
                            }
                        }
                        this.fbIndex++;
                        this.tIndex++;
                        this.x++;
                    }
                    this.fbIndex -= 8;
                    this.fbIndex += 0x100;
                    this.tIndex -= 0x10;
                    this.y++;
                }
            }
            else
            {
                this.fbIndex = (dy << 8) + dx;
                this.tIndex = 0x3f;
                this.y = 0;
                while (this.y < 8)
                {
                    this.x = 0;
                    while (this.x < 8)
                    {
                        if (((this.x >= srcx1) && (this.x < srcx2)) && ((this.y >= srcy1) && (this.y < srcy2)))
                        {
                            this.palIndex = this.pix[this.tIndex];
                            this.tpri = priTable[this.fbIndex];
                            if ((this.palIndex != 0) && (pri <= (this.tpri & 0xff)))
                            {
                                fBuffer[this.fbIndex] = palette[this.palIndex + palAdd];
                                this.tpri = (this.tpri & 0xf00) | pri;
                                priTable[this.fbIndex] = this.tpri;
                            }
                        }
                        this.fbIndex++;
                        this.tIndex--;
                        this.x++;
                    }
                    this.fbIndex -= 8;
                    this.fbIndex += 0x100;
                    this.y++;
                }
            }
        }
    }

    public virtual void renderSimple(int dx, int dy, int[] fBuffer, int palAdd, int[] palette)
    {
        this.tIndex = 0;
        this.fbIndex = (dy << 8) + dx;
        this.y = 8;
        while (this.y != 0)
        {
            this.x = 8;
            while (this.x != 0)
            {
                this.palIndex = this.pix[this.tIndex];
                if (this.palIndex != 0)
                {
                    fBuffer[this.fbIndex] = palette[this.palIndex + palAdd];
                }
                this.fbIndex++;
                this.tIndex++;
                this.x--;
            }
            this.fbIndex -= 8;
            this.fbIndex += 0x100;
            this.y--;
        }
    }

    public virtual void renderSmall(int dx, int dy, int[] buffer, int palAdd, int[] palette)
    {
        this.tIndex = 0;
        this.fbIndex = (dy << 8) + dx;
        this.y = 0;
        while (this.y < 4)
        {
            this.x = 0;
            while (this.x < 4)
            {
                this.c = (palette[this.pix[this.tIndex] + palAdd] >> 2) & 0x3f3f3f;
                this.c += (palette[this.pix[this.tIndex + 1] + palAdd] >> 2) & 0x3f3f3f;
                this.c += (palette[this.pix[this.tIndex + 8] + palAdd] >> 2) & 0x3f3f3f;
                this.c += (palette[this.pix[this.tIndex + 9] + palAdd] >> 2) & 0x3f3f3f;
                buffer[this.fbIndex] = this.c;
                this.fbIndex++;
                this.tIndex += 2;
                this.x++;
            }
            this.tIndex += 8;
            this.fbIndex += 0xfc;
            this.y++;
        }
    }

    public virtual void setScanline(int sline, short b1, short b2)
    {
        this.initialized = true;
        this.tIndex = sline << 3;
        this.x = 0;
        while (this.x < 8)
        {
            this.pix[this.tIndex + this.x] = ((b1 >> (7 - this.x)) & 1) + (((b2 >> ((7 - this.x) & 0x1f)) & 1) << 1);
            if (this.pix[this.tIndex + this.x] == 0)
            {
                this.opaque[sline] = false;
            }
            this.x++;
        }
    }

    public virtual void stateLoad(ByteBuffer buf)
    {
        this.initialized = buf.readBoolean();
        for (int i = 0; i < 8; i++)
        {
            this.opaque[i] = buf.readBoolean();
        }
        for (int j = 0; j < 0x40; j++)
        {
            this.pix[j] = buf.readInt();
        }
    }

    public virtual void stateSave(ByteBuffer buf)
    {
        buf.putBoolean(this.initialized);
        for (int i = 0; i < 8; i++)
        {
            buf.putBoolean(this.opaque[i]);
        }
        for (int j = 0; j < 0x40; j++)
        {
            buf.putInt(this.pix[j]);
        }
    }

    public virtual short[] Buffer
    {
        set
        {
            this.y = 0;
            while (this.y < 8)
            {
                this.setScanline(this.y, value[this.y], value[this.y + 8]);
                this.y++;
            }
        }
    }
}

